feat: Managed bypass tokens - #309
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an admin-managed “bypass token” mechanism that can selectively bypass Turnstile and/or rate limiting, tracks per-user usage for leak-defense, and optionally auto-cleans up accounts created/used via bypass tokens.
Changes:
- Introduce new bypass-token data model + EF migration (tokens, per-user use tracking, enum types).
- Add middleware + services to resolve
X-OpenShock-Bypass-Tokenonce per request and allow synchronous downstream checks (rate limiting / Turnstile). - Add admin endpoints for managing bypass tokens and a cron job to delete eligible bypass-token-used accounts after a grace period.
Reviewed changes
Copilot reviewed 28 out of 29 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| Cron/Jobs/DeleteBypassTokenUsedAccountsJob.cs | Hourly job that deletes non-admin user accounts eligible for bypass-token auto-cleanup. |
| Common/Services/Bypass/ResolvedBypassToken.cs | Defines cached per-request resolved bypass token model stored in HttpContext.Items. |
| Common/Services/Bypass/IBypassTokenService.cs | Service contract for resolving tokens and recording per-user usage (incl. admin-block behavior). |
| Common/Services/Bypass/BypassTokenService.cs | EF-backed implementation: resolve token, bump counters, and upsert per-user usage records. |
| Common/OpenShockServiceHelper.cs | Registers bypass token service and adds rate-limiter bypass partition logic. |
| Common/OpenShockMiddlewareHelper.cs | Adds BypassTokenMiddleware before UseRateLimiter to enable same-request bypass. |
| Common/OpenShockDb/User.cs | Adds navigation for bypass-token usage records. |
| Common/OpenShockDb/OpenShockContext.cs | Adds DbSets, enum mapping, and EF model configuration for bypass token tables/types. |
| Common/OpenShockDb/BypassTokenUserUse.cs | New entity tracking first/last use and per-user use count of a bypass token. |
| Common/OpenShockDb/BypassToken.cs | New entity for admin-managed bypass tokens (types, hash, counters, cleanup settings). |
| Common/Models/BypassTokenType.cs | New Postgres-mapped enum for bypass token capabilities (turnstile, rate_limit). |
| Common/Migrations/OpenShockContextModelSnapshot.cs | Updates snapshot to include new enum + entities/tables. |
| Common/Migrations/20260526192123_AddBypassTokens.Designer.cs | Generated EF designer for the bypass-token migration. |
| Common/Migrations/20260526192123_AddBypassTokens.cs | Migration creating bypass token tables and Postgres enum. |
| Common/Middleware/BypassTokenMiddleware.cs | Middleware that resolves bypass token header and caches the result in-context. |
| Common/Extensions/HttpContextExtensions.cs | Adds header parsing + HttpContext.Items helpers for resolved bypass token. |
| Common/Constants/AuthConstants.cs | Adds X-OpenShock-Bypass-Token header constant. |
| API/Services/Turnstile/CloudflareTurnstileService.cs | Allows Turnstile to succeed when a resolved bypass token includes Turnstile. |
| API/Controller/Tokens/ReportTokens.cs | Records bypass usage post-auth and rejects bypass usage for admin accounts. |
| API/Controller/Admin/DTOs/CreateBypassTokenDto.cs | DTOs for creating/patching bypass tokens, incl. create-time validation rules. |
| API/Controller/Admin/DTOs/BypassTokenDto.cs | DTOs for returning bypass token metadata and newly-created secrets. |
| API/Controller/Admin/BypassTokenRotate.cs | Endpoint to rotate a bypass token secret and reset usage counters. |
| API/Controller/Admin/BypassTokenPatch.cs | Endpoint to patch bypass token properties (name, types, cleanup settings). |
| API/Controller/Admin/BypassTokenList.cs | Endpoint to list all bypass tokens. |
| API/Controller/Admin/BypassTokenDelete.cs | Endpoint to delete a bypass token. |
| API/Controller/Admin/BypassTokenCreate.cs | Endpoint to create a bypass token and return the generated secret. |
| API/Controller/Account/SignupV2.cs | Records bypass usage for newly created accounts (post-signup). |
| API/Controller/Account/PasswordResetInitiateV2.cs | Records bypass usage by email and silently aborts for admin emails to prevent enumeration. |
| API/Controller/Account/LoginV2.cs | Records bypass usage post-auth and rejects bypass usage for admin accounts. |
Files not reviewed (1)
- Common/Migrations/20260526192123_AddBypassTokens.Designer.cs: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public sealed class PatchBypassTokenDto | ||
| { | ||
| [MaxLength(HardLimits.ApiKeyNameMaxLength)] | ||
| public string? Name { get; init; } | ||
|
|
||
| public IReadOnlyList<BypassTokenType>? Types { get; init; } | ||
|
|
||
| public bool? AutoCleanupUsers { get; init; } | ||
|
|
||
| public TimeSpan? AutoCleanupAfter { get; init; } | ||
| } |
| if (body.Name is not null) token.Name = body.Name.Trim(); | ||
| if (body.Types is not null) token.Types = [.. body.Types.Distinct()]; | ||
| if (body.AutoCleanupUsers is not null) token.AutoCleanupUsers = body.AutoCleanupUsers.Value; | ||
| if (body.AutoCleanupAfter is not null) token.AutoCleanupAfter = body.AutoCleanupAfter; | ||
|
|
||
| if (token.AutoCleanupUsers && token.AutoCleanupAfter is null) | ||
| return Problem("AutoCleanupAfter is required when AutoCleanupUsers is true.", statusCode: StatusCodes.Status400BadRequest); | ||
|
|
|
|
||
| // An admin-issued bypass token resolved earlier in the pipeline counts as a Turnstile pass | ||
| // if it carries the Turnstile type. The middleware already bumped use counters; controllers | ||
| // separately call IBypassTokenService.RecordUseAsync after auth so admin-using requests can |
| ); | ||
| } | ||
|
|
||
| // Admin accounts must never be authenticated through a bypassed flow — RecordUseAsync returns |
| // An admin-issued bypass token resolved earlier in the pipeline counts as a Turnstile pass | ||
| // if it carries the Turnstile type. The middleware already bumped use counters; controllers | ||
| // separately call IBypassTokenService.RecordUseAsync after auth so admin-using requests can | ||
| // be rejected and per-user cleanup can run. | ||
| var resolvedBypass = _httpContextAccessor.HttpContext?.GetResolvedBypassToken(); | ||
| if (resolvedBypass is not null && resolvedBypass.Types.Contains(BypassTokenType.Turnstile)) | ||
| return new Success(); |
This reverts commit 636b767.
…s-tokens # Conflicts: # Common/OpenShockMiddlewareHelper.cs
develop moved the Turnstile verification out of LoginV2 into _Turnstile.cs and dropped the OpenShock.API.Errors using along with it, but this branch's admin bypass guard still references TurnstileError. RoleType also moved into the OpenShock.Common.OpenShockDb namespace with the Internal.Net extraction.
|
Warning Review limit reached
Next review available in: 23 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
No description provided.